route.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { NextRequest, NextResponse } from "next/server";
  2. import { STORAGE_KEY } from "../../../constant";
  3. async function handle(
  4. req: NextRequest,
  5. { params }: { params: { path: string[] } },
  6. ) {
  7. if (req.method === "OPTIONS") {
  8. return NextResponse.json({ body: "OK" }, { status: 200 });
  9. }
  10. const folder = STORAGE_KEY;
  11. const fileName = `${folder}/backup.json`;
  12. const requestUrl = new URL(req.url);
  13. const endpoint = requestUrl.searchParams.get("endpoint");
  14. const [protocol, ...subpath] = params.path;
  15. const endpointPath = subpath.join("/");
  16. // only allow MKCOL, GET, PUT
  17. if (req.method !== "MKCOL" && req.method !== "GET" && req.method !== "PUT") {
  18. return NextResponse.json(
  19. {
  20. error: true,
  21. msg: "you are not allowed to request " + params.path.join("/"),
  22. },
  23. {
  24. status: 403,
  25. },
  26. );
  27. }
  28. // for MKCOL request, only allow request ${folder}
  29. if (
  30. req.method == "MKCOL" &&
  31. !new URL(endpointPath).pathname.endsWith(folder)
  32. ) {
  33. return NextResponse.json(
  34. {
  35. error: true,
  36. msg: "you are not allowed to request " + params.path.join("/"),
  37. },
  38. {
  39. status: 403,
  40. },
  41. );
  42. }
  43. // for GET request, only allow request ending with fileName
  44. if (
  45. req.method == "GET" &&
  46. !new URL(endpointPath).pathname.endsWith(fileName)
  47. ) {
  48. return NextResponse.json(
  49. {
  50. error: true,
  51. msg: "you are not allowed to request " + params.path.join("/"),
  52. },
  53. {
  54. status: 403,
  55. },
  56. );
  57. }
  58. // for PUT request, only allow request ending with fileName
  59. if (
  60. req.method == "PUT" &&
  61. !new URL(endpointPath).pathname.endsWith(fileName)
  62. ) {
  63. return NextResponse.json(
  64. {
  65. error: true,
  66. msg: "you are not allowed to request " + params.path.join("/"),
  67. },
  68. {
  69. status: 403,
  70. },
  71. );
  72. }
  73. const targetUrl = `${protocol}://${endpoint + endpointPath}`;
  74. const method = req.method;
  75. const shouldNotHaveBody = ["get", "head"].includes(
  76. method?.toLowerCase() ?? "",
  77. );
  78. const fetchOptions: RequestInit = {
  79. headers: {
  80. authorization: req.headers.get("authorization") ?? "",
  81. },
  82. body: shouldNotHaveBody ? null : req.body,
  83. method,
  84. // @ts-ignore
  85. duplex: "half",
  86. };
  87. const fetchResult = await fetch(targetUrl, fetchOptions);
  88. console.log("[Any Proxy]", targetUrl, {
  89. status: fetchResult.status,
  90. statusText: fetchResult.statusText,
  91. });
  92. return fetchResult;
  93. }
  94. export const POST = handle;
  95. export const GET = handle;
  96. export const OPTIONS = handle;
  97. export const runtime = "edge";